package com.example.shiroplusdemo.service;

import com.example.shiroplusdemo.entity.FrontPage;
import com.example.shiroplusdemo.entity.User;
import com.example.shiroplusdemo.entity.UserOnlineVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * @author ：Anitaxiaofeng
 * @description：
 * @create 2018-01-13
 **/
@Service
@Slf4j
public class UserService {

    @Autowired
    private RedisSessionDAO redisSessionDAO;

    @Autowired
    private SessionManager sessionManager;

    public Page<UserOnlineVO> getUserSessionPage(FrontPage frontPage){

        //redis实现了shiro的session的dao，所以可以从redisSessionDao中获取session列表
        Collection<Session> sessions = redisSessionDAO.getActiveSessions();
        Iterator<Session> it = sessions.iterator();
        List<UserOnlineVO> onlineUserList = new ArrayList<>();
        while(it.hasNext()){
            //这是shiro已经存入session的，现在直接取就是了
            Session session = it.next();
            //标记为已踢出的不加入在线列表
            if(session.getAttribute("kickout")==null?false:true) continue;
            UserOnlineVO userOnlineVO= getSessionVO(session);
            onlineUserList.add(userOnlineVO);
        }
        //将List换成Page
        Page<UserOnlineVO> onlineUserPage = getPage(onlineUserList,frontPage.getPage(), frontPage.getRows());
        return onlineUserPage;

    }

    private  UserOnlineVO getSessionVO(Session session){
        //获取Session的登录信息
        Object objLogin = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
        if(null == objLogin){
            return null;
        }
        //确保是SimplePrincipalCollection对象
        if(objLogin instanceof SimplePrincipalCollection){
            SimplePrincipalCollection spc = (SimplePrincipalCollection)objLogin;
            //获取用户登录的SimpleAuthenticationInfo对象
            objLogin = spc.getPrimaryPrincipal();
            if(null!=objLogin&&objLogin instanceof User){
                UserOnlineVO userOnlineVO = new UserOnlineVO((User)objLogin);
                userOnlineVO.setLastAccess(session.getLastAccessTime());
                userOnlineVO.setHost(session.getHost());
                userOnlineVO.setSessionId(session.getId().toString());
                userOnlineVO.setLastLoginTime(session.getLastAccessTime());
                //会话到期TTL(ms)
                userOnlineVO.setTimeout(session.getTimeout());
                userOnlineVO.setStartTime(session.getStartTimestamp());
                userOnlineVO.setSessionStatus(false);
                return userOnlineVO;
            }
        }
        return null;
    }

    public Page<UserOnlineVO> getPage(List<UserOnlineVO> allList,int page,int size) {
        int totalSize = allList.size();
        int index = page * size;
        if(totalSize == 0||index>totalSize){
            return new PageImpl<UserOnlineVO>(new ArrayList<>(),new PageRequest(page,size),totalSize);
        }
        int endIndex = index+size;
        if(endIndex>totalSize){
            endIndex = totalSize;
        }
        return new PageImpl<UserOnlineVO>(allList.subList(index,endIndex),new PageRequest(page,size),totalSize);
    }

    /**
     * 根据sessionId执行强制退出
     * @param sessionId
     */
    public void kickout(Serializable sessionId){
        //根据sessionId获取session对象
        Session  kickoutSession = sessionManager.getSession(new DefaultSessionKey(sessionId));
        kickoutSession.setAttribute("kickout",true);
    }
}


